import flash.events.AsyncErrorEvent;
import flash.events.Event;
import flash.events.NetStatusEvent;
import flash.events.MouseEvent;
import flash.display.MovieClip;
import flash.media.Camera;
import flash.media.Microphone;
import flash.media.Video;
import flash.net.NetConnection;
import flash.net.NetStream;

class Main extends flash.display.MovieClip
{
	#if play
		static var app:String="/minimal/ns/play";
	#elseif record
		static var app:String="/minimal/ns/record";
	#elseif live
		static var app:String="/minimal/ns/live";
	#end
	var nc:NetConnection;
	var ns:NetStream;
	var ns2:NetStream;
	var cam:Camera;
	var mic:Microphone;
	var player:Video;
	
	public static function main()
	{
		flash.Lib.current.addChild(new Main());
	}
	public function new()
	{
		super();
		cam = Camera.getCamera();
		mic = Microphone.getMicrophone();
		player = new Video();
		player.x = 500;
		player.y = 200;
		addChild(player);
		
		nc = new NetConnection();
		nc.client=this;
		nc.objectEncoding = 0;
		nc.addEventListener(NetStatusEvent.NET_STATUS, onConnectionStatus);
		nc.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onConnectionError);
		
		addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
	}
	function onAddedToStage(event:Event)
	{
		removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
		var uri = getUri();
		trace("connecting to rtmp://" + uri);
		nc.connect("rtmp://"+uri);
	}
	
	//monitor netconnection
	function onConnectionError(event:AsyncErrorEvent):Void
	{
		trace("nc:"+event.currentTarget+", onConnectionError error: " + event.error);
	}
	function onConnectionStatus(event:NetStatusEvent):Void
	{
		var msg = "nc:"+event.currentTarget+", onConnectionStatus code:"+event.info.code;
		if(event.info.description!=null)
			msg += ", description:" + event.info.description;
		trace(msg);
		
		if(event.info.code == "NetConnection.Connect.Success")
		{
			ns = new NetStream(nc);
			ns.client=this;
			ns.addEventListener(NetStatusEvent.NET_STATUS, onStreamStatus);
			ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onStreamError);
			
			//tests: -D [play|record|live]
			#if play
				testPlay();
			#elseif record
				testRecord();
			#elseif live
				testShared();
			#end
		}
	}
	
	//monitor netstream(s)
	function onStreamStatus(event:NetStatusEvent):Void
	{
		var msg = "ns:"+event.currentTarget+", onStreamStatus code="+event.info.code;
		if(event.info.description !=null)
			msg+=", description=" + event.info.description;
		trace(msg);
	}
	function onStreamError(event:AsyncErrorEvent):Void
	{
		trace("ns:"+event.currentTarget+", onStreamError currentTarget="+event.currentTarget + ", text="+event.text+", error=" + event.error);
	}
	function onStreamMetaData(data:Dynamic)
	{
		trace("ns: onStreamMetaData");
		for(i in Reflect.fields(data))
			trace(i+"="+Reflect.field(data, i));
		if(data.width>0 && data.height>0)
		{
			player.width=data.width;
			player.height=data.height;
		}
	}
	
	//tests:
	function testPlay()
	{
		player.attachNetStream(ns);
		trace("========== started playing a file : applications/minimal/ns/play/streams/sample.flv ========== ");
		ns.play("sample");//plays "sample.flv" from streams folder on the server
	}
	function testRecord()
	{
		player.attachCamera(cam);
		ns.attachCamera(cam);
		ns.attachAudio(mic);
		trace("========== started recording to file : applications/minimal/ns/record/streams/webcam-recorded.flv ========== ");
		ns.publish("webcam-recorded", "record");
		
	}
	function testShared()
	{
		ns.attachCamera(cam);
		ns.attachAudio(mic);
		trace("========== started publishing to live stream name : test ========== ");
		ns.publish("test", "live");//publishes a live stream (not recorded) with name "test"

		var ns2 = new NetStream(nc);
		ns2.client = this;
		ns2.addEventListener(NetStatusEvent.NET_STATUS, onStreamStatus);
		ns2.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onStreamError);
		player.attachNetStream(ns2);
		trace("========== started watching (your own) live stream : test ========== ");
		ns2.play("test");//subscribes to a live stream with name "test" (in this example you are watching your own stream.)
		
		trace('CLICK THE STAGE to send a message to all subscribers');
		stage.addEventListener(MouseEvent.CLICK, onStageClick);
	}
	function onStageClick(event:Event)
	{
		trace('ns: sending: "testMessage", 7, "seven", true, Date.now(), ["zero", "one", {two:2, three:3}');
		ns.send("testMessage", 7, 'seven', true, Date.now(), ["zero", "one", {two:2, three:3}] );//calls the functino testMessage on every subscriber of this stream
	}
	function testMessage(i:Int, s:String, b:Bool, d:Date, a:Array<Dynamic>)
	{
		trace('received:');
		trace(i);
		trace(s);
		trace(b);
		trace(d);
		trace(a);
	}
	function getUri():String
	{
		var parameters:Dynamic = flash.Lib.current.loaderInfo.parameters;
		//trace(parameters);
		var u = Reflect.field(parameters, "uri");
		if(u!=null)
			return u;
		var h = Reflect.field(parameters, "host");
		var p = Reflect.field(parameters, "port");
		var a = Reflect.field(parameters, "app");
		return (h==null?"localhost":h) + (p==null?":1935":":"+p) + (a==null?app:a);
	}
}

